#region Using Statements

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Text;
using System.Web;
using System.Web.Configuration;

#endregion

namespace Dotss.Core
{

    public class ServerConfig
    {
	
		/// <summary>
		/// The port DOTSS operates on
		/// </summary>
		public const int STATE_PORT = 42424;
	
	}


    public class ClientConfig : ConfigurationSection
    {

		#region Fields

		public const string SECTION_ID = "DOTSS.Client";
		private static ClientConfig _Settings = null;

		#endregion
        
		/// <summary>
		/// Static accessor to the settings of the Dotss Client
		/// </summary>
		public static ClientConfig Settings
        {
            get
            {
				if (_Settings == null)

					try
					{

						Configuration config;
						config = LocateConfigurationSection();

						// Identify our configuration section
						foreach (ConfigurationSection section in config.Sections)
						{

							if (!typeof (ClientConfig).AssemblyQualifiedName.Contains(section.SectionInformation.Type)) continue;

							_Settings = (ClientConfig) section;
							break;

						}

						// Exit if the section is unavailable
						if (_Settings == null) throw new Exception("Unable to find a matching ConfigSection of type 'Dotss.Core.ClientConfig, Dotss.Core'");

					} catch (Exception ex)
					{
						throw new ApplicationException("Missing or invalid DOTSS.Client configuration section named '" + SECTION_ID + "' of type '" + typeof(ClientConfig).FullName + "'", ex);
					}
            	return _Settings;
            }
        }

		#region Configuration Properties

		[ConfigurationProperty("Server")]
		public ServersCollection Servers
		{
			get { return (ServersCollection)base["Server"]; }
		}

		/// <summary>
		/// Session Timeout value in minutes
		/// </summary>
		[ConfigurationProperty("timeout", DefaultValue = "20", IsRequired = false)]
		[IntegerValidator(MinValue = 1)]
		public int Timeout
		{
			get { return Convert.ToInt32(base["timeout"]); }
		}

		/// <summary>
		/// Configurable name of the environment that the webserver is presenting the application in.
		/// </summary>
		/// <remarks>Typical usage may be to label an environment as DEV, STAGE, or PROD</remarks>
		[ConfigurationProperty("environment", DefaultValue = "", IsRequired = false)]
		public string EnvironmentName
		{
			get { return base["environment"].ToString(); }
		}

		/// <summary>
		/// Name of the application state is being saved for
		/// </summary>
		[ConfigurationProperty("application", DefaultValue = "", IsRequired = false)]
		public string ApplicationName
		{
			get { return base["application"].ToString(); }
		}

		[ConfigurationProperty("compression", DefaultValue = "true", IsKey = false, IsRequired = false)]
		public bool Compression
		{
			get { return bool.Parse(base["compression"].ToString()); }
		}

		[ConfigurationProperty("connectionstringname", DefaultValue = "DOTSS", IsKey = false, IsRequired = false)]
		public string ConnectionStringName
		{
			get { return base["connectionstringname"].ToString(); }
		}

		/// <summary>
		/// ConnectionString specified for the application
		/// </summary>
		public string ConnectionString
		{
			get { return ConfigurationManager.ConnectionStrings[ConnectionStringName].ConnectionString; }
		}

		#endregion
		
		#region Private Methods

		/// <summary>
		/// Locate the app.config or web.config file
		/// </summary>
		/// <returns>Configuration reference to the current config file</returns>
		private static Configuration LocateConfigurationSection()
		{

			Configuration config;

			if (HttpContext.Current != null)		// In web mode
			{
				config = WebConfigurationManager.OpenWebConfiguration(HttpContext.Current.Request.ApplicationPath);
			}
			else
			{
				config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
			}

			return config;

		}

		#endregion

	}

    [ConfigurationCollection(typeof(ServerElement))]
    public class ServersCollection : ConfigurationElementCollection
    {

        public ServerElement this[int idx]
        {
            get { return (ServerElement) BaseGet(idx);  }
        }

        protected override ConfigurationElement CreateNewElement()
        {
            return new ServerElement();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((ServerElement) element).Address;
        }

    }

    public class ServerElement : ConfigurationElement
    {

        /// <summary>
        /// Address to connect to as a DOTSS server
        /// </summary>
        [ConfigurationProperty("address", DefaultValue = "127.0.0.1", IsKey = true, IsRequired = true)]
        public string Address
        {
            get { return base["address"].ToString(); }
        }

    }

}
